/// Author: QP
/// Version: 1.0
/// Date:2021/07/01
/// 互联互通文档SQL模型基类
Class HCC.SQL.Base Extends %RegisteredObject [ System = 3 ]
{

/// 设置对象的Modified标志，从而强制类型校验
/// 模版方法
Method SetModified() As %Status [ CodeMode = objectgenerator, ForceGenerate ]
{
    // 不处理基类
    Quit:%classname="HCC.SQL.Base" $$$OK
    // 不处理以下属性
    Do %code.WriteLine(" Set tSC=1")
    Do %code.WriteLine(" Try ")
    Do %code.WriteLine(" { ")
    Do %code.WriteLine("    Do $system.CLS.SetModified(##this, 1)")
    For n=1:1:%compiledclass.Properties.Count()
    {
        Set tPropDef = %compiledclass.Properties.GetAt(n)
        
        //不处理计算属性、多维属性 
        Set tNotProcess = tPropDef.Calculated||(tPropDef.MultiDimensional)||((tPropDef.Transient)&&(tPropDef.Cardinality=""))||($E(tPropDef.Name,1,2)="%%")
        Continue:(tNotProcess)
        
        Set tPropType = tPropDef.Type,tClassType=""
        
        Set tClassType = ##class(HIP.DataGov.Util).GetClassType(tPropType)
        If tClassType="serial"
        {
            Do %code.WriteLine("    do .."_tPropDef.Name_".SetModified()")
        }
    }
    Do %code.WriteLine("    Return tSC")
    Do %code.WriteLine(" }")
    Do %code.WriteLine(" catch e")
    Do %code.WriteLine(" {")
    Do %code.WriteLine("    Set tSC = $$$ERROR(e.Code,e.Data)")
    Do %code.WriteLine(" }")
    Do %code.WriteLine(" Quit tSC")
    Quit $$$OK
}

/// 检查数据元基数约束
/// 模版方法
/// pDocType: 1-53 文档类型编号
/// pDocNo: 文档编号
Method CheckDECardinality(pDocType, pDocNo) As %Status [ CodeMode = objectgenerator, ForceGenerate ]
{
    // 不处理基类和非持久化类
    Quit:%classname="HCC.SQL.Base" $$$OK
    Set tClassType = ##class(HIP.DataGov.Util).GetClassType(%classname), %tTableName=""
    Quit:(tClassType'="persistent") $$$OK
    
    &SQL(SELECT JSON_ARRAYAGG(id) into :%tSerialList FROM %Dictionary.CompiledClass where id %Startswith 'HCC.SQL.Document' and ClassType='serial')
    
    &SQL(select TABLE_SCHEMA||'.'||TABLE_NAME into :%tTableName from INFORMATION_SCHEMA.TABLES where CLASSNAME=:%classname)
    
    Do %code.WriteLine(" Set tSC=1")
    //Do %code.WriteLine(" Set:(pSQLClass="""") pSQLClass="""_%classname_"""")
    
    Do %code.WriteLine(" Try ")
    Do %code.WriteLine(" { ")
    Do %code.WriteLine("    Set tInt = """",tLsProp=""""") 
    Do %code.WriteLine("    Set tInt = $O(^WS.DocDECard(pDocType,"""_%tTableName_""",tInt))") 
    Do %code.WriteLine("    While tInt'=""""") 
    Do %code.WriteLine("    {") 
    Do %code.WriteLine("        Set tProp=$G(^WS.DocDECard(pDocType,"""_%tTableName_""",tInt))") 
    Do %code.WriteLine("        Set tTmpValue=""""") 
    Do %code.WriteLine("        Set tTmp=""Q ..""_tProp_""=""""""""""")
    Do %code.WriteLine("        Set tTmpValue= $XECUTE(tTmp)")
    Do %code.WriteLine("        Set:(tTmpValue=1) $LI(tLsProp,$LL(tLsProp)+1)=tProp") 
    Do %code.WriteLine("        Set tInt = $O(^WS.DocDECard(pDocType,"""_%tTableName_""",tInt))") 
    Do %code.WriteLine("    }") 
    // log the invalidation
    Do %code.WriteLine("    Set tObjId = pDocNo,tTable = """_%tTableName_"""")
    Do %code.WriteLine("    If $LL(tLsProp)>0  ")
    Do %code.WriteLine("    { ")
    Do %code.WriteLine("        Set tSC=$$$ERROR(-100001,""值不能为空"")")
    Do %code.WriteLine("        Set tCol = $LISTTOSTRING(tLsProp,"","")")
    Do %code.WriteLine("        &SQL(")
    Do %code.WriteLine("        INSERT INTO HIP_DataGov.Log(SQLTable,RecordId,ColumnName,ErrorCode,Error) ")
    Do %code.WriteLine("        VALUES(:tTable,:tObjId,:tCol,'-100001','值不能为空')")
    Do %code.WriteLine("        )")
    Do %code.WriteLine("    } ")

    
    For n=1:1:%compiledclass.Properties.Count()
    {
        Set tPropDef = %compiledclass.Properties.GetAt(n)
        //不处理计算属性、多维属性、父方、一方
        Set tNotProcess = tPropDef.Calculated||(tPropDef.MultiDimensional)||((tPropDef.Transient)&&(tPropDef.Cardinality=""))||($E(tPropDef.Name,1,2)="%%")||(tPropDef.Cardinality="parent") || (tPropDef.Cardinality="one")
        Continue:(tNotProcess)

        Set tPropType = tPropDef.Type
        ;Set tClassType=##class(HIP.DataGov.Util).GetClassType(tPropType)
        // for children and many side of relationship (persistent), loop all members
        If (tPropDef.Cardinality="children") || (tPropDef.Cardinality="many")
        {
            Do %code.WriteLine("    for i=1:1:.."_tPropDef.Name_".Count()")
            Do %code.WriteLine("    { ")
            Do %code.WriteLine("        Set tTmpSC = .."_tPropDef.Name_".GetAt(i).CheckDECardinality(pDocType,pDocNo)")
            Do %code.WriteLine("        Set:($$$ISERR(tTmpSC)) tSC = tTmpSC")
            Do %code.WriteLine("    }")
        }
        // for persistent properties, run their check DE Cardinality method
        ElseIf (tPropType["HCC.SQL.Document.") && (%tSerialList'[(""""_tPropType_""""))
        {
            Do %code.WriteLine("    If $IsObject(.."_tPropDef.Name_")")
            Do %code.WriteLine("    {")
            Do %code.WriteLine("        Set tSC= .."_tPropDef.Name_".CheckDECardinality(pDocType,pDocNo)")
            Do %code.WriteLine("    }")
        } 
    }
    Do %code.WriteLine("    Return tSC")
    Do %code.WriteLine(" }")
    Do %code.WriteLine(" catch e")
    Do %code.WriteLine(" {")
    Do %code.WriteLine("    Set tSC = $$$ERROR(e.Code,e.Data)")
    Do %code.WriteLine(" }")
    Do %code.WriteLine(" Quit tSC")
    Quit $$$OK
}

}
